#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import subprocess
import re
import socket
import datetime
from datetime import date
import os, errno
import argparse




parser = argparse.ArgumentParser()
parser.add_argument("--pcap_file", "-p", type=str,help="input pcap file to be translated")
args = parser.parse_args()

pcap_file = args.pcap_file.strip()

pcap_dissected_file = subprocess.check_output(["tshark", '-V', '-r' , pcap_file], stderr=subprocess.STDOUT)
pcap_hex_file = subprocess.check_output(["tshark", '-x', '-O', 'sctp', '-r', pcap_file])
pcap_dissected_list = {}

# split file content in lines
lines = pcap_dissected_file.splitlines()
message     = {}
item_index  = 0;
item_string = " "
line_index  = 0
sctp_index  = 0
fsm_state="search_frame"
for line in lines:
    print ("INPUT LINE %d:  %s  | fsm_state %s" % (line_index, line, fsm_state))
    line_index += 1
    line = line.lower().strip()
    if line != "":       
        if fsm_state == "search_frame":
            if line.startswith("frame"):
                message = {}
                sctp_index = 0
                partition = line.split(' ',3)
                message['frame'] = int(partition[1].strip(':'))
                fsm_state = "search_ip"
                print("Found Frame %d" % (message['frame']))

        if fsm_state == "search_frame_or_sctp":
            if line.startswith("frame"):
                message = {}
                sctp_index = 0
                partition = line.split(' ',3)
                message['frame'] = int(partition[1].strip(':'))
                fsm_state = "search_ip"
                print("Found Frame %d" % (message['frame']))
            elif line.startswith("stream control transmission protocol"):
                fsm_state = "fill_sctp"
                sctp_index += 1
                message['sctp_fields'][sctp_index] = 0

        elif fsm_state == "search_ip":
            if line.startswith("internet protocol version"):
                fsm_state = "fill_ip"
                message['ip_fields'] = 0
                print("Found in Frame %d IP" % (message['frame']))

        elif fsm_state == "fill_ip":
            if line.startswith("header length"):
                partition = line.split(' ',4)
                message['ip_header_length'] = int(partition[2])
                message['ip_fields'] += 1
                print("Found in Frame %d IP header length %d" % (message['frame'], int(partition[2])))
            if line.startswith("total length"):
                partition = line.split(' ',4)
                message['ip_total_length'] = int(partition[2])
                message['ip_fields'] += 1
                print("Found in Frame %d IP Total Length %d" % (message['frame'], int(partition[2])))
            if line.startswith("protocol"):
                partition = line.split(' ',4)
                if partition[1] != "sctp" and partition[2] != "(132)" :
                    print("Info did not found in Frame %d SCTP, try next" % (message['frame']))
                    fsm_state="search_frame"
                    continue
                else:
                    message['ip_protocol'] = partition[1]
                    message['ip_fields'] += 1
                    print("Found in Frame %d SCTP" % (message['frame']))
            if message['ip_fields'] == 3:
                fsm_state = "search_sctp"
                print("in Frame %d searching S1AP" % (message['frame']))
                        
        elif fsm_state == "search_sctp":
            if line.startswith("stream control transmission protocol"):
                fsm_state = "fill_sctp"
                message['sctp_fields'] = [0,0,0]
                message['sctp_fields'][sctp_index] = 0
                
        elif fsm_state == "fill_sctp":
            if line.startswith("source port"):
                partition = line.split(' ',4)
                message['source port'] = [0,0,0]
                message['source port'][sctp_index] = int(partition[2])
                message['sctp_fields'][sctp_index] += 1
            elif line.startswith("destination port"):
                partition = line.split(' ',4)
                message['destination port']= [0,0,0]
                message['destination port'][sctp_index] = int(partition[2])
                message['sctp_fields'][sctp_index] += 1
            elif line.startswith("chunk length"):
                partition = line.split(' ',4)
                message['chunk length'] = [0,0,0]
                message['chunk length'][sctp_index] = int(partition[2])
                message['sctp_fields'][sctp_index] += 1
            elif line.startswith("stream identifier"):
                partition = line.split(' ',4)
                message['stream identifier'] = [0,0,0]
                message['stream identifier'][sctp_index] = int(partition[2],0)
                message['sctp_fields'][sctp_index] += 1
            elif line.startswith("stream sequence number"):
                partition = line.split(' ',4)
                message['stream sequence number'] = [0,0,0]
                message['stream sequence number'][sctp_index] = int(partition[3])
                message['sctp_fields'][sctp_index] += 1
            elif line.startswith("chunk padding"):
                partition = line.split(' ',4)
                message['chunk padding'] = [0,0,0]
                message['chunk padding'][sctp_index] = int(partition[2])
                message['sctp_fields'][sctp_index] += 1
            if message['sctp_fields'][sctp_index] == 6:
                fsm_state = "search_s1ap"
                
        elif fsm_state == "search_s1ap":
            if line.startswith("s1 application protocol"):
                fsm_state = "fill_s1ap"
                message['s1ap_fields'] = [0,0,0]
                message['s1ap_fields'][sctp_index] = 0
                print("in Frame %d Filling S1AP" % (message['frame']))
                        
        elif fsm_state == "fill_s1ap":
            if line.startswith("s1ap-pdu:"):
                partition = line.split(' ')
                message['pdu'] = ["","",""]
                message['pdu'][sctp_index] = partition[1]
                message['s1ap_fields'][sctp_index] += 1
                message['items'] = [{},{},{}]
                #message['items'][sctp_index] = {}
            elif line.startswith("procedurecode:"):
                partition = line.split(' ')
                message['procedurecode'] = ["","",""]
                message['procedurecode'][sctp_index] = partition[1]
                message['s1ap_fields'][sctp_index] += 1
            elif line.startswith("protocolies"):
                partition = line.split(' ')
                message['protocolies'] = [0,0,0]
                message['protocolies'][sctp_index] = int(partition[1])
                message['s1ap_fields'][sctp_index] += 1
            elif line.startswith("item"):
                partition = line.split(' ')
                item_index  = int(partition[1].strip(':'))
                if len(partition) > 2: # may be item string in content of items ! (example: supported TAs)
                    item_string = partition[2]
                    message['items'][sctp_index][item_string] = ' '
                    print("Found in Frame %d S1AP Item %d %s" % (message['frame'], item_index, item_string))
            elif line.startswith("nas-pdu") and message['items'][sctp_index][item_string] == "id-nas-pdu":
                    partition = line.split(' ')
                    nas_bytes = partition[1]
                    message['items'][sctp_index][item_string] = nas_bytes

            if message['s1ap_fields'][sctp_index] >= 3:
                if len(message['items'][sctp_index]) == message['protocolies'][sctp_index]:
                    pcap_dissected_list[message['frame']] = message
                    fsm_state = "search_frame_or_sctp"

for message in pcap_dissected_list:
    print("Message:\n" )
    print("    %s\n" % (message))

lines = pcap_hex_file.splitlines()
message = {}
frame_index = 0
message_index = 0
s1ap_payload = 0
sctp_index  = 0
fsm_state="search_frame"
for line in lines:
    print ("HEX INPUT LINE:  %s " % line)
    line = line.lower().strip()
    if line != "":       
        if fsm_state == "search_frame":
            if line.startswith("frame"):
                partition = line.split(' ',3)
                frame_index = int(partition[1].strip(':'))
                if frame_index in pcap_dissected_list:
                    fsm_state = "search_sctp"
                    sctp_index  = 0
                    message = pcap_dissected_list[frame_index]
                    message['s1ap_byte_offset'] = [0,0,0]
                    message['s1ap_dumped'] = [[],[],[]]
                    
        if fsm_state == "search_frame_or_sctp":
            if line.startswith("frame"):
                sctp_index = 0
                partition = line.split(' ',3)
                frame_index = int(partition[1].strip(':'))
                if frame_index in pcap_dissected_list:
                    fsm_state = "search_sctp"
                    sctp_index  = 0
            elif line.startswith("stream control transmission protocol"):
                fsm_state = "search_s1ap_in_sctp"
                sctp_index += 1
                message['sctp_fields'][sctp_index] = 0
                                
        elif fsm_state == "search_sctp":
            if line.startswith("stream control transmission protocol"):
                fsm_state = "search_s1ap_in_sctp"

        elif fsm_state == "search_s1ap_in_sctp":
            if line.startswith("payload protocol identifier: s1 application protocol (s1ap) (18)"):
                fsm_state = "search_s1ap"
                       
        elif fsm_state == "search_s1ap":
            if line.startswith("s1 application protocol"):
                fsm_state = "fill_s1ap"
                message['s1ap_byte_offset'][sctp_index] = 0
                message['s1ap_dumped'][sctp_index] = []
                        
        elif fsm_state == "fill_s1ap":
            if not line.startswith("frame"):
                bytes = line.split(' ')
                byte_index = int(bytes[0],16)
                if byte_index ==  message['s1ap_byte_offset'][sctp_index]:
                    message['s1ap_byte_offset'][sctp_index] += 16
                    for byte in bytes:
                        message['s1ap_dumped'][sctp_index].append(byte)
                        message['s1ap_byte_offset'][sctp_index] += 1
                else:
                    fsm_state="search_frame_or_sctp"
            
print ("  %s " % ( pcap_dissected_list ) )

